# 实时视频风格迁移 -- 油画 ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- 本项目是一个基于 Quectel Pi M2 智能主控板(RK3576)实现的 NPU 油画风格迁移示例,提供 **两种** 使用方式: - **实时视频风格迁移**:MIPI 摄像头(IMX219)采集画面,送入 RK3576 NPU 运行 FastNeuralStyle 油画风格迁移模型(udnie INT8),实时转换后输出到屏幕显示,完整展示"摄像头取帧 → NPU 推理 → 屏幕显示"的链路。 - **单张图片风格迁移**:读取本地图片,经同一模型转换后按原图尺寸回缩放并保存,适合预览效果或批量出图。 两种模式共用同一套 RKNN 推理封装(`librknn_style.so` + `rknn_style.py`)。 # 开发资源汇总 ## 开发配件清单 > **提示**:开发配件只是作为参考,不同的开发环境可能会有所差异。 | **配件名称** | **数量** | **规格参数** | | --- | --- | --- | | Quectel Pi M2 智能主控板 | 1 块 | RK3576,8 核,板载 NPU | | IMX219 MIPI 摄像头模块 | 1 个 | camera0 → /dev/video33,camera1 → /dev/video51 | | 显示屏(可选) | 1 块 | HDMI 或 MIPI DSI,需运行 Wayland 桌面 | | Type-C 电源适配器 | 1 个 | 5V/3A,或使用板载供电口 | | FPC 排线、亚克力支架 | 若干 | 摄像头固定与走线 | ## 配件实物参考 *(此处插入主控板 + 摄像头 + 显示屏的实物照片)* # 快速上手 ## 开发准备 **Quectel Pi M2** 智能主控板出厂默认搭载 **Debian 13(trixie)** 系统镜像,本示例所需的 Python、GStreamer、OpenCV 以及 RKNN 运行时均已预装,无需再次烧录镜像或编译推理库,仅需按如下步骤操作即可。 本示例的关键技术指标如下: | **项目** | **参数** | | --- | --- | | 采集分辨率 | 640×480 @ 30 fps(NV12) | | 推理输入尺寸 | 160×160,3 通道 | | 推理精度 | INT8(RK3576) | | 风格模型 | udnie(FastNeuralStyle) | | 实时帧率 | 约 2.7 FPS(RK3576 实测 2.64~2.76 FPS) | | 单图转换耗时 | 594×559 图片约 350 ms(含读写约 0.4 s) | | 显示方式 | Wayland(waylandsink),窗口或全屏 | | 推理运行时 | librknnrt API 2.3.2 / NPU 驱动 0.9.8 | ## 硬件连接 完成以下所有硬件连接操作: 1. **摄像头连接**:将 IMX219(或兼容的 MIPI 摄像头)通过 FPC 排线接入主控板的 MIPI CSI 接口,camera0 对应 `/dev/video33`,camera1 对应 `/dev/video51`。 2. **显示连接**:通过 HDMI 或 MIPI DSI 接入显示屏,并确保桌面用户 `q` 已登录 Wayland 会话(`/run/user/1001/wayland-0`),因为显示使用 `waylandsink`。 3. **供电连接**:接入 Type-C 电源(5V/3A),上电后系统自动进入桌面。 > **提示**:连接完成后可用 `v4l2-ctl --list-devices` 确认摄像头是否在位,若在 `rkisp_mainpath (platform:rkisp-vir0)` 下看到 `/dev/video33`,即代表 camera0 已正常识别。 ## 项目实现 ### 获取代码 工程已预置在板端的 `/m2_demo_youhua` 目录,可通过 git 查看或更新: ```bash cd /m2_demo_youhua git status git pull ``` 若需重新获取,从 GitHub 仓库克隆: ```bash git clone https://github.com/Quectel-Pi/demo-rknn-style-transfer.git ``` 目录结构如下: ``` /m2_demo_youhua/ ├── run_on_board.sh 启动摄像头 demo ├── stop_on_board.sh 停止摄像头 demo ├── convert_image.sh 单图转换入口 ├── build.sh 重新编译 librknn_style.so(通常不需要执行) ├── src/rknn_style.c build.sh 的源码 ├── librknn_style.so 已编译好的推理包装库 ├── rknn_style.py RKNN ctypes 封装,两个主程序共用 ├── oil_painting_cam.py 摄像头 demo 主程序 ├── image_style.py 单图转换主程序 ├── cat.png / cat_painting.png 单图转换示例(原图 / 效果图) └── models/rknn/ └── udnie-9_int8_rk3576.rknn ``` ### 安装依赖 本镜像已预装全部依赖,一般情况下无需安装。可用如下命令校验: ```bash python3 -c "import cv2, numpy; print(cv2.__version__, numpy.__version__)" python3 -c "import gi; gi.require_version('Gst', '1.0'); from gi.repository import Gst; print('gst ok')" ls /usr/lib/librknnrt.so ``` 依赖清单供参考: | **依赖项** | **Debian 包名** | **作用** | | --- | --- | --- | | Python 3 | python3 | 主程序运行环境 | | OpenCV | python3-opencv | 图像缩放与色彩转换 | | NumPy | python3-numpy | 张量数据组织 | | GStreamer 绑定 | python3-gi | 摄像头采集与屏幕显示管线 | | GStreamer 插件 | gstreamer1.0-plugins-base、-good、-bad | v4l2src、videoconvert、waylandsink | | RKNN 运行时 | librknnrt.so(/usr/lib) | NPU 推理 | ### 运行程序 ```bash cd /m2_demo_youhua ./run_on_board.sh # 后台运行,640x480 窗口 ./run_on_board.sh --fullscreen # 全屏 ./run_on_board.sh --fg # 前台运行(Ctrl+C 退出) ./stop_on_board.sh # 停止 tail -f /tmp/demo_run.log # 查看后台日志 ``` 首次成功启动时,日志中可看到模型与管线信息: ``` [rknn] 模型 /m2_demo_youhua/models/rknn/udnie-9_int8_rk3576.rknn [rknn] api=2.3.2 driver=0.9.8 [rknn] 输入 160x160 C3 [info] 5 帧, 2.64 FPS ``` ## 单张图片风格迁移 除实时视频外,工程还提供单图转换入口 `convert_image.sh`,推理过程与摄像头 demo 完全一致(160×160 INT8),转换结果默认按原图尺寸回缩放后保存。 ```bash cd /m2_demo_youhua ./convert_image.sh cat.png # 输出 cat_udnie.png(同目录) ./convert_image.sh cat.png -o out/cat_paint.jpg # 指定文件名,自动建目录 ./convert_image.sh cat.png -o out/ # 指定目录,自动命名 ./convert_image.sh cat.png -d out/paintings # 同上,显式目录参数 ./convert_image.sh a.png b.png -d out/ # 批量转换 ./convert_image.sh cat.png -o 'out/{stem}_{model}.png' ``` 输出命名规则: | **写法** | **结果** | | --- | --- | | 不给 | `<输入目录>/<输入名>_<风格>.<原扩展名>` | | `-o 路径/文件名.jpg` | 使用该文件名;无扩展名时沿用源扩展名 | | `-o 目录/` 或以 `/` 结尾 | 目录内自动命名,目录不存在会自动创建 | | `-o 已存在的目录` | 目录内自动命名 | | `-d 目录` | 目录内自动命名 | | `{stem}` / `{model}` | 在文件名中替换为输入名 / 风格名 | 常用参数: | **参数** | **说明** | | --- | --- | | `-m/--model` | 风格,本分支仅 `udnie` | | `--precision` | `int8`(本分支仅提供 INT8 模型) | | `--keep-size` | 保留 160×160 模型输出尺寸,不做放大 | | `--interp` | 回缩放插值:`nearest`/`linear`/`cubic`/`lanczos`(默认 lanczos) | | `-q/--quiet` | 只输出错误信息 | 正常转换时的日志如下: ``` [img] input: cat.png model: /m2_demo_youhua/models/rknn/udnie-9_int8_rk3576.rknn size: model input 160x160, 3 channel(s) [594x559] -> [594x559] 350 ms cat_udnie.png ``` ## 操控方式 > 程序启动后无需额外操作,画面会持续以油画风格实时刷新;以 root 启动时脚本会自动切换到桌面用户 `q` 再运行,以访问 Wayland 显示。 | **操作** | **功能** | | --- | --- | | `./run_on_board.sh` | 后台运行,窗口模式 | | `./run_on_board.sh --fullscreen` | 全屏显示 | | `./run_on_board.sh --windowed` | 源尺寸窗口显示(默认) | | `./run_on_board.sh --fg` | 前台运行,Ctrl+C 退出 | | `./run_on_board.sh --camera /dev/video51` | 切换到 camera1 | | `./run_on_board.sh --frames 100` | 跑 100 帧后自动退出(0 = 一直跑) | | `./stop_on_board.sh` | 停止后台实例 | | `tail -f /tmp/demo_run.log` | 实时查看帧率与日志 | # 应用演示 下图为本工程 `cat.png` 的原图与经 udnie 模型转换后的效果对比: ```{image} images/image_Gpccbn2H4oYEJ5xe0jncwSfvnJb.webp :width: 594px :height: 559px :align: center ``` ```{image} images/image_XckvbgbjboUIG0xzVY5cqOw5nub.webp :width: 594px :height: 559px :align: center ``` 摄像头实时模式的效果可通过 `./run_on_board.sh` 直接观察;如需录制演示视频,建议使用 `--fullscreen` 模式并配合屏幕录制。 # 常见问题及解决方案 ## 程序启动 15 秒后自动退出,提示未收到帧 **现象:** ``` [错误] 15 秒未收到任何帧 —— 检查相机 /dev/video33 是否可用 ``` **解决方案:** - 使用 `v4l2-ctl --list-devices` 确认摄像头已识别,camera0 应为 `/dev/video33`。 - 检查 FPC 排线是否插紧、方向是否正确。 - 若使用 camera1,需显式指定:`./run_on_board.sh --camera /dev/video51`。 ## 日志出现 libv4l2 pixformat 报错 **现象:** ``` libv4l2: error getting pixformat: Invalid argument ``` **解决方案:** - 这是 `v4l2src` 在 ISP 直出通路上的无害告警,脚本已设置 `GST_V4L2_FORCE_LIBV4L2=0` 规避;只要后续能正常出帧(日志出现 `[info] N 帧`)即可忽略。 ## 启动报错 Wayland socket not found **现象:** ``` [error] Wayland socket not found: /run/user/1001/wayland-0; make sure q is logged in ``` **解决方案:** - 确认桌面用户已登录图形界面,`waylandsink` 必须运行在 Wayland 会话中。 - 若桌面用户不是 `q`,通过环境变量指定:`DEMO_USER=your_user ./run_on_board.sh`。 ## 提示缺少 librknn_style.so 或找不到模型 **现象:** ``` RuntimeError: 缺少 /m2_demo_youhua/librknn_style.so, 请先在本目录执行 ./build.sh 找不到风格 'udnie' 的 int8 模型, 预期在 /m2_demo_youhua/models/rknn ``` **解决方案:** - 确认 `librknn_style.so` 与 `models/rknn/udnie-9_int8_rk3576.rknn` 均存在于工程目录,本部署分支只保留运行所需文件。 - 推理库丢失时才需要重新编译,编译前需准备 Rockchip 专有的 `rknn_api.h`: ```bash apt-get install -y build-essential mkdir -p /usr/include/rknn # 从 SDK 的 external/rknpu2/runtime/Linux/librknn_api/include/ 拷贝 rknn_api.h 到该目录 cd /m2_demo_youhua && ./build.sh ``` - `build.sh` 会按 `./include` → `/usr/include/rknn` → SDK 目录的顺序查找头文件;在开发机交叉编译时可通过 `REPO` 指定 SDK 根目录。 ## 帧率偏低(约 2.7 FPS) **现象:** ``` [info] 10 帧, 2.76 FPS ``` **解决方案:** - 该帧率是当前 FastNeuralStyle 模型在 RK3576 NPU 上的正常水平(推理输入 160×160、INT8),并非异常。 - 若需更高帧率,可减小推理输入分辨率、换用更轻量的风格模型,或降低显示分辨率。 - 排查性能时可临时加 `--frames 30` 做定点压测,观察日志中的 FPS 是否稳定。 ## 推理初始化失败 **现象:** ``` RuntimeError: rknn_init 失败: rknn_init 失败 ret=-1 ``` **解决方案:** - 确认 `/usr/lib/librknnrt.so` 存在,且与模型版本匹配(本模型面向 RK3576,运行时 API 2.3.2 / 驱动 0.9.8)。 - 确认使用的是 `udnie-9_int8_rk3576.rknn`,其他平台转换的模型无法在本板运行。 # 技术支持与贡献 如在使用过程中遇到问题,欢迎在 [移远官方论坛]() 提交技术咨询,我们的技术支持团队将及时为您解答。 项目仓库: https://github.com/Quectel-Pi/demo-rknn-style-transfer 欢迎提交 Issue 反馈问题或 Pull Request 贡献代码改进!